package cn.s1995.sloth.bizs.event.listener;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.s1995.sloth.bizs.constant.BizCst;
import cn.s1995.sloth.common.core.constant.enums.hint.Hint;
import cn.s1995.sloth.bizs.entity.*;
import cn.s1995.sloth.bizs.event.SubmitOrderEvent;
import cn.s1995.sloth.bizs.event.order.SubmitOrderOrder;
import cn.s1995.sloth.bizs.exception.BizException;
import cn.s1995.sloth.bizs.mapper.ProdMapper;
import cn.s1995.sloth.bizs.mapper.SkuMapper;
import cn.s1995.sloth.bizs.oo.dto.ShopCartItemDTO;
import cn.s1995.sloth.bizs.oo.dto.ShopCartItemDiscountDTO;
import cn.s1995.sloth.bizs.oo.dto.ShopCartOrderDTO;
import cn.s1995.sloth.bizs.oo.vo.ShopCartOrderMergerVO;
import cn.s1995.sloth.bizs.service.CartService;
import cn.s1995.sloth.bizs.service.OrderAddressService;
import cn.s1995.sloth.bizs.service.ProdService;
import cn.s1995.sloth.bizs.service.SkuService;
import cn.s1995.sloth.common.security.service.SlothUser;
import cn.s1995.sloth.common.security.util.SecurityUtils;
import cn.s1995.sloth.common.sequence.sequence.Sequence;
import lombok.AllArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * SubmitOrderListener
 *
 * @author Lex
 * @description 提交订单监听器
 * @date 2024/01/02 14:24
 */
@Component
@AllArgsConstructor
public class SubmitOrderListener {

    private final OrderAddressService orderAddressService;
    private final ProdService productService;
    private final SkuService skuService;
    private final CartService cartService;
    private final SkuMapper skuMapper;
    private final ProdMapper productMapper;
    private final Sequence orderSequence;


    /**
     * 提交订单
     * @param event
     */
    @EventListener(SubmitOrderEvent.class)
    @org.springframework.core.annotation.Order(SubmitOrderOrder.DEFAULT)
    public void defaultSubmitOrderListener(SubmitOrderEvent event) {
        LocalDateTime now = LocalDateTime.now();
        SlothUser user = SecurityUtils.getUser();

        ShopCartOrderMergerVO mergerOrder = event.getMergerOrder();

        // 订单商品参数
        List<ShopCartOrderDTO> shopCartOrders = mergerOrder.getShopCartOrders();

        List<Long> cartIds = new ArrayList<>();
        // 商品skuId为key 需要更新的sku为value的map
        Map<Long, Sku> skuStocksMap = new HashMap<>(16);
        // 商品productId为key 需要更新的product为value的map
        Map<Long, Prod> prodStocksMap = new HashMap<>(16);

        // 把订单地址保存到数据库
        OrderAddress orderAddress = BeanUtil.copyProperties(mergerOrder.getUserAddr(), OrderAddress.class);
        if (Objects.isNull(orderAddress)) {
            throw new BizException(Hint.APP_PLEASE_SELECT_THE_RECEIVING_ADDRESS);
        }
        orderAddress.setId(null);
        orderAddress.setUid(user.getId());
        orderAddress.setCreateTime(now);
        orderAddressService.save(orderAddress);

        // 订单地址id
        Long orderAddressId = orderAddress.getId();


        // 每个店铺生成一个订单
        for (ShopCartOrderDTO shopCartOrderDto : shopCartOrders) {
            createOrder(event, now, user, cartIds, skuStocksMap, prodStocksMap, orderAddressId, shopCartOrderDto);
        }

        // 删除购物车的商品信息
        if (!cartIds.isEmpty()) {
            cartService.removeShopCartItemsByCartIds(user.getId(), cartIds);

        }

        // 更新sku库存
        skuStocksMap.forEach((key, sku) -> {

            if (skuMapper.updateStocks(sku) == 0) {
                skuService.removeSkuCacheBySkuId(key, sku.getProdId());
                throw new BizException(Hint.APP_PROD_STOCKS_NOT_ENOUGH, sku.getProdName());
            }
        });

        // 更新商品库存
        prodStocksMap.forEach((prodId, prod) -> {

            if (productMapper.updateStocks(prod) == 0) {
                productService.removeProductCacheByProdId(prodId);
                throw new BizException(Hint.APP_PROD_STOCKS_NOT_ENOUGH, prod.getName());
            }
        });

    }

    /**
     * 创建订单
     * @param event
     * @param now
     * @param user
     * @param cartIds
     * @param skuStocksMap
     * @param prodStocksMap
     * @param orderAddressId
     * @param shopCartOrderDto
     */
    private void createOrder(SubmitOrderEvent event, LocalDateTime now, SlothUser user, List<Long> cartIds, Map<Long, Sku> skuStocksMap, Map<Long, Prod> prodStocksMap, Long orderAddressId, ShopCartOrderDTO shopCartOrderDto) {
        Long orderId = Long.valueOf(orderSequence.nextNo());
        shopCartOrderDto.setOrderId(orderId);

        Long shopId = shopCartOrderDto.getShopId();

        // 订单商品名称
        StringBuilder orderProdName = new StringBuilder(100);

        List<OrderItem> orderItems = new ArrayList<>();

        List<ShopCartItemDiscountDTO> shopCartItemDiscounts = shopCartOrderDto.getShopCartItemDiscounts();
        for (ShopCartItemDiscountDTO shopCartItemDiscount : shopCartItemDiscounts) {
            List<ShopCartItemDTO> shopCartItems = shopCartItemDiscount.getShopCartItems();
            for (ShopCartItemDTO shopCartItem : shopCartItems) {
                Sku sku = checkAndGetSku(shopCartItem.getSkuId(), shopCartItem, skuStocksMap);
                Prod product = checkAndGetProd(shopCartItem.getProdId(), shopCartItem, prodStocksMap);
                orderItems.add(buildOrderItem(now, user, orderId, shopId, orderProdName, shopCartItem, sku, product));

                if (Objects.nonNull(shopCartItem.getCartId()) && shopCartItem.getCartId() != 0) {
                    cartIds.add(shopCartItem.getCartId());
                }
            }

        }

        orderProdName.subSequence(0, Math.min(orderProdName.length() - 1, 1000));
        if (orderProdName.lastIndexOf(StrUtil.COMMA) == orderProdName.length() - 1) {
            orderProdName.deleteCharAt(orderProdName.length() - 1);
        }


        // 订单信息
        Order order = buildOrder(now, user, orderAddressId, shopCartOrderDto, orderId, orderProdName, orderItems);
        event.getOrders().add(order);

    }

    /**
     * 构建订单
     * @param now
     * @param user
     * @param orderAddressId
     * @param shopCartOrderDto
     * @param orderId
     * @param orderProdName
     * @param orderItems
     * @return
     */
    private Order buildOrder(LocalDateTime now, SlothUser user, Long orderAddressId, ShopCartOrderDTO shopCartOrderDto, Long orderId, StringBuilder orderProdName, List<OrderItem> orderItems) {
        Order order = new Order();

        order.setId(orderId);
        // 订单商品名称
        order.setProdName(orderProdName.toString());
        // 用户信息
        order.setUid(user.getId());
        order.setUserNickname(user.getNickname());
        order.setUserAvatar(user.getAvatar());
        // 店铺信息
        order.setShopId(shopCartOrderDto.getShopId());
        order.setShopName(shopCartOrderDto.getShopName());
        order.setShopAvatar(shopCartOrderDto.getShopAvatar());
        // 商品总额
        order.setOrderAmount(shopCartOrderDto.getTotal());
        // 实际总额
        order.setActualAmount(shopCartOrderDto.getActualTotal());
        order.setState(BizCst.Order.State.unpay);
        order.setUpdateTime(now);
        order.setCreateTime(now);
        order.setIsPayed(Boolean.FALSE);
        order.setNum(shopCartOrderDto.getTotalCount());
        order.setOrderAddressId(orderAddressId);
        order.setReduceAmount(NumberUtil.sub(NumberUtil.add(shopCartOrderDto.getTotal(), shopCartOrderDto.getTransfee()), shopCartOrderDto.getActualTotal()));
        order.setFreightAmount(shopCartOrderDto.getTransfee());
        order.setRemark(shopCartOrderDto.getRemarks());

        order.setOrderItems(orderItems);
        return order;
    }

    /**
     * 构建订单项
     * @param now
     * @param user
     * @param orderNumber
     * @param shopId
     * @param orderProdName
     * @param shopCartItem
     * @param sku
     * @param product
     * @return
     */
    private OrderItem buildOrderItem(LocalDateTime now, SlothUser user, Long orderNumber, Long shopId, StringBuilder orderProdName, ShopCartItemDTO shopCartItem, Sku sku, Prod product) {
        OrderItem orderItem = new OrderItem();
        orderItem.setShopId(shopId);
        orderItem.setOrderId(orderNumber);
        orderItem.setProdId(sku.getProdId());
        orderItem.setSkuId(sku.getId());
        orderItem.setSkuName(sku.getSkuName());
        orderItem.setNum(shopCartItem.getProdNum());
        orderItem.setProdName(sku.getProdName());
        orderItem.setPic(StrUtil.isNotBlank(sku.getPic()) ? sku.getPic() : product.getPic());
        orderItem.setAmount(shopCartItem.getAmount());
        // TODO 计算运费
        orderItem.setFreightAmount(BigDecimal.ZERO);
        orderItem.setUid(user.getId());
        orderItem.setTotalAmount(shopCartItem.getTotalAmount());
        orderItem.setCreateTime(now);
        orderItem.setIsComment(Boolean.FALSE);
        orderProdName.append(orderItem.getProdName()).append(",");
        //推广员卡号
        // orderItem.setDistributionCardNo(shopCartItem.getDistributionCardNo());
        return orderItem;
    }

    /**
     * 检查并获取商品信息
     * @param prodId
     * @param shopCartItem
     * @param prodStocksMap
     * @return
     */
    @SuppressWarnings({"Duplicates"})
    private Prod checkAndGetProd(Long prodId, ShopCartItemDTO shopCartItem, Map<Long, Prod> prodStocksMap) {
        Prod product = productService.getProduct(prodId);
        if (product == null) {
            throw new BizException(Hint.APP_CONTAINS_UNRECOGNIZED_PRODUCTS);
        }

        if (BooleanUtil.isFalse(product.getIsSale())) {
            throw new BizException(Hint.APP_PROD_NOT_SALE, product.getName());
        }

        // 商品需要改变的库存
        Prod mapProduct = prodStocksMap.get(prodId);

        if (mapProduct == null) {
            mapProduct = new Prod();
            mapProduct.setTotalStocks(0);
            mapProduct.setId(prodId);
            mapProduct.setName(product.getName());

        }

        if (product.getTotalStocks() != -1) {
            mapProduct.setTotalStocks(mapProduct.getTotalStocks() + shopCartItem.getProdNum());
            prodStocksMap.put(product.getId(), mapProduct);
        }

        // -1为无限库存
        if (product.getTotalStocks() != -1 && mapProduct.getTotalStocks() > product.getTotalStocks()) {
            throw new BizException(Hint.APP_PROD_STOCKS_NOT_ENOUGH, product.getName());
        }

        return product;
    }

    /**
     * 检查并获取sku信息
     * @param skuId
     * @param shopCartItem
     * @param skuStocksMap
     * @return
     */
    @SuppressWarnings({"Duplicates"})
    private Sku checkAndGetSku(Long skuId, ShopCartItemDTO shopCartItem, Map<Long, Sku> skuStocksMap) {
        // 获取sku信息
        Sku sku = skuService.getSku(skuId);
        if (sku == null) {
            throw new BizException(Hint.APP_CONTAINS_UNRECOGNIZED_PRODUCTS);
        }

        if (BooleanUtil.isFalse(sku.getIsSale())) {
            throw new BizException(Hint.APP_PROD_NOT_SALE, sku.getProdName());
        }
        // -1为无限库存
        if (sku.getActualStocks() != -1 && shopCartItem.getProdNum() > sku.getActualStocks()) {
            throw new BizException(Hint.APP_PROD_STOCKS_NOT_ENOUGH, sku.getProdName());
        }

        if (sku.getActualStocks() != -1) {
            Sku mapSku = new Sku();
            mapSku.setProdId(sku.getProdId());
            // 这里的库存是改变的库存
            mapSku.setActualStocks(shopCartItem.getProdNum());
            mapSku.setId(sku.getId());
            mapSku.setProdName(sku.getProdName());
            skuStocksMap.put(sku.getId(), mapSku);
        }
        return sku;
    }

}
